/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package nvPlaces;

import java.util.Iterator;
import org.nViron.nvCommon.*;
import java.util.Vector;
import nvOrganism.nvOrganism;
import org.nViron.nvData.nvDataEntity;
import org.nViron.nvOrganic.nvOrganic;
import org.nViron.nvRender.nvRenderer;

/**
 *
 * @author Roland
 */
public class nvPlace extends nvOrganism {

    private nvOrganic organic = null;
    private nvPosition center = new nvPosition();
    private Vector entities = new Vector();
    private Vector previousOrganics = new Vector();
    private nvPlacesMgr placesMgr;

    public nvPlace(nvPlacesMgr placesMgr) {
        super(placesMgr);
        this.placesMgr = placesMgr;
    }

    public nvPlace(nvPlacesMgr placeMgr, nvDataEntity entity, nvClusterer clusterer) {
        super(placeMgr);
        this.placesMgr = placeMgr;
        addEntity(entity, clusterer);
    }

    public nvPosition getCenter() {
        return center;
    }

    public Vector getEntities() {
        return entities;
    }

    public nvPlacesMgr getPlaceMgr() {
        return placesMgr;
    }

    public Vector getPreviousOrganics() {
        return previousOrganics;
    }

    public void addEntity(nvDataEntity newEntity, nvClusterer clusterer) {
        entities.add(newEntity);

        nvPosition newCenter = clusterer.getCenter(entities);

        if (organic == null) {
            center = newCenter;
            organic = new nvOrganic(placesMgr.getSimulator().getOrganicsMgr(), this);
            return;
        }

        if (!placesMgr.getClusterer().keepCenter(center, newCenter))
        {
            synchronized(organic) {
                center = newCenter;
                nvOrganic newOrganic = (nvOrganic)organic.clone();
                newOrganic.setPosition(center);
                newOrganic.getStateMgr().setState(nvStateMgr.SPAWN);
                organic.getStateMgr().setState(nvStateMgr.DEGENERATING);
                synchronized(previousOrganics) {
                    previousOrganics.add(organic);
                }
                organic = newOrganic;
                organic.getStateMgr().setState(nvStateMgr.SPROUTING);
            }
        }
    }

    @Override
    public void update() {
        // TODO update internal states

        // update organics
        if (organic != null) {
            synchronized(organic) {
                organic.update();
            }
        }
        synchronized(previousOrganics) {
            for (Iterator it = previousOrganics.iterator(); it.hasNext(); ) {
                nvOrganic prev = (nvOrganic)it.next();
                prev.update();
                if (prev.getStateMgr().getState() == nvStateMgr.DEAD) {
                    it.remove();
                }
            }
        }
    }

    @Override
    public void render(nvRenderer renderer) {
        renderer.renderPlace(this);
        // render organics
        if (organic != null) {
            synchronized(organic) {
                organic.render(renderer);
            }
        }
        synchronized(previousOrganics) {
            for (Iterator it = previousOrganics.iterator(); it.hasNext(); ) {
                nvOrganic prev = (nvOrganic)it.next();
                prev.render(renderer);
            }
        }
    }

    public void removeEntity(nvDataEntity entity) {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    public int getNumEntities() {
        return entities.size();
    }
}
